import router from '@/router'
import { userStore } from '@/store'
import axios, { AxiosResponse, AxiosError, InternalAxiosRequestConfig } from 'axios'
import { showFailToast } from 'vant'
import { clearToken, getToken } from './storage'

type ApiResponse<T = any> = {
  code: number
  msg: string
  data: T
}

const request = axios.create({
  baseURL: import.meta.env.VITE_POST_URL,
  timeout: 5000,
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
  },
  withCredentials: false, // 允许携带Cookie
  transformRequest: [
    (data, headers) => {
      const contentType = headers['Content-Type'] || headers['content-type']

      // json
      if (contentType?.includes('application/json')) {
        return JSON.stringify(data)
      }
      return data
    }
  ]
})

// 是否在处理登录过期中
let isHandlingExpired = false

const handleLoginExpired = (msg: string) => {
  if (isHandlingExpired) return
  isHandlingExpired = true

  const user = userStore()
  user.clearUserInfo()
  clearToken()
  showFailToast(msg)

  // 记录跳转路径（非登录页时）
  const currentRoute = router.currentRoute.value
  const pageRequiresAuth = currentRoute.meta.requireAuth === true
  const isLoginPage = currentRoute.path === '/login'

  if (!isLoginPage && pageRequiresAuth) {
    localStorage.setItem('redirectAfterLogin', currentRoute.fullPath)
  }

  setTimeout(() => {
    router.push('/login')
    isHandlingExpired = false
  }, 1000)
}

// 请求拦截器
request.interceptors.request.use(
  (config: InternalAxiosRequestConfig): InternalAxiosRequestConfig => {
    const token = getToken()
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`
    }
    return config
  },
  (error: AxiosError): Promise<AxiosError> => {
    showFailToast('请求发送失败，请稍后重试')
    return Promise.reject(error)
  }
)

// 响应拦截器
request.interceptors.response.use(
  (response: AxiosResponse<ApiResponse>): AxiosResponse<ApiResponse> => {
    const { code, msg } = response.data

    // 处理会话过期
    if (response.headers['x-session-expired'] === 'true') {
      handleLoginExpired(msg || '登录已过期，请重新登录')
      throw new Error('SESSION_EXPIRED')
    }

    // 处理未登录 或 token过期
    if (code === -1 && ['请先登录', '无效的token或已过期'].includes(msg)) {
      handleLoginExpired(msg || '请先登录')
      throw new Error('SESSION_EXPIRED')
    }

    // 处理其他业务错误
    if (code !== 0) {
      showFailToast(msg || '操作失败')
      throw new Error('REQUEST_FAILED')
    }
    return response
  },
  (error: AxiosError<ApiResponse>): Promise<AxiosError<ApiResponse>> => {
    const response = error.response
    const errorMsg = response?.data?.msg || '网络异常，请稍后重试'

    // 检查错误响应中的会话过期标识
    if (response?.headers['x-session-expired'] === 'true') {
      handleLoginExpired(errorMsg || '登录已过期，请重新登录')
      return Promise.reject(error)
    }

    // 处理HTTP 401错误作为补充
    if (response?.status === 401) {
      handleLoginExpired('登录已过期，请重新登录')
      return Promise.reject(error)
    }

    // 其他网络错误
    showFailToast(errorMsg)
    return Promise.reject(error)
  }
)

export default request
